using System;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Input;
namespace Microsoft.Phone.Controls.Maps.Core
{
	internal class ManipulationHandler
	{
		private const ushort TapDistanceThreshold = 30;
		private const ushort DoubleTapTimeThreshold = 500;
		private const ushort TapAndHoldTimeThreshold = 2000;
		private const ushort DragThresholdForFlick = 3;
		private bool isTap;
		private bool isTapPending;
		private Timeout lastTap;
		private Point lastTapOrigin;
		private long lastTapTimestamp;
		private long tapStartTimestamp;
		private UIElement root;
		private Point lastTranslation;
		public event EventHandler<GestureEventArgs> Tap
		{
			[MethodImpl(32)]
			add
			{
				this.Tap = (EventHandler<GestureEventArgs>)Delegate.Combine(this.Tap, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.Tap = (EventHandler<GestureEventArgs>)Delegate.Remove(this.Tap, value);
			}
		}
		public event EventHandler<GestureEventArgs> DoubleTap
		{
			[MethodImpl(32)]
			add
			{
				this.DoubleTap = (EventHandler<GestureEventArgs>)Delegate.Combine(this.DoubleTap, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.DoubleTap = (EventHandler<GestureEventArgs>)Delegate.Remove(this.DoubleTap, value);
			}
		}
		public event EventHandler<GestureEventArgs> TapAndHold
		{
			[MethodImpl(32)]
			add
			{
				this.TapAndHold = (EventHandler<GestureEventArgs>)Delegate.Combine(this.TapAndHold, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.TapAndHold = (EventHandler<GestureEventArgs>)Delegate.Remove(this.TapAndHold, value);
			}
		}
		public event EventHandler<GestureEventArgs> Pan
		{
			[MethodImpl(32)]
			add
			{
				this.Pan = (EventHandler<GestureEventArgs>)Delegate.Combine(this.Pan, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.Pan = (EventHandler<GestureEventArgs>)Delegate.Remove(this.Pan, value);
			}
		}
		public event EventHandler<GestureEventArgs> Flick
		{
			[MethodImpl(32)]
			add
			{
				this.Flick = (EventHandler<GestureEventArgs>)Delegate.Combine(this.Flick, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.Flick = (EventHandler<GestureEventArgs>)Delegate.Remove(this.Flick, value);
			}
		}
		public event EventHandler<GestureEventArgs> Pinch
		{
			[MethodImpl(32)]
			add
			{
				this.Pinch = (EventHandler<GestureEventArgs>)Delegate.Combine(this.Pinch, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.Pinch = (EventHandler<GestureEventArgs>)Delegate.Remove(this.Pinch, value);
			}
		}
		public event EventHandler<GestureEventArgs> Stretch
		{
			[MethodImpl(32)]
			add
			{
				this.Stretch = (EventHandler<GestureEventArgs>)Delegate.Combine(this.Stretch, value);
			}
			[MethodImpl(32)]
			remove
			{
				this.Stretch = (EventHandler<GestureEventArgs>)Delegate.Remove(this.Stretch, value);
			}
		}
		private static bool IsDoubleTap(Point previousPoint, long previousTimestamp, Point currentPoint, long currentTimestamp)
		{
			return !PhysicsHelper.ExceedsThreshold(TimeSpan.FromTicks(currentTimestamp - previousTimestamp), 500L) && !PhysicsHelper.ExceedsThreshold(PhysicsHelper.Delta(previousPoint, currentPoint), 30L);
		}
		public ManipulationHandler(UIElement element)
		{
			if (element == null)
			{
				throw new ArgumentNullException("element");
			}
			element.add_ManipulationStarted(new EventHandler<ManipulationStartedEventArgs>(this.OnManipulationStarted));
			element.add_ManipulationCompleted(new EventHandler<ManipulationCompletedEventArgs>(this.OnManipulationCompleted));
			element.add_ManipulationDelta(new EventHandler<ManipulationDeltaEventArgs>(this.OnManipulationDelta));
			this.root = element;
		}
		internal void Unload()
		{
			if (this.lastTap != null)
			{
				this.lastTap.Cancel();
			}
		}
		private void OnManipulationStarted(object sender, ManipulationStartedEventArgs e)
		{
			if (e.get_Handled())
			{
				return;
			}
			e.set_Handled(true);
			this.isTap = true;
			this.tapStartTimestamp = DateTime.get_Now().get_Ticks();
		}
		private void OnManipulationDelta(object sender, ManipulationDeltaEventArgs e)
		{
			DateTime now = DateTime.get_Now();
			if (e.get_Handled())
			{
				return;
			}
			e.set_Handled(true);
			UIElement uIElement = e.get_OriginalSource() as UIElement;
			UIElement uIElement2 = sender as UIElement;
			if (uIElement != null && uIElement2 != null)
			{
				Point origin = uIElement.TransformToVisual(uIElement2).Transform(e.get_ManipulationOrigin());
				bool flag = false;
				bool flag2 = false;
				if (e.get_DeltaManipulation().get_Scale().get_X() > 0.0 && e.get_DeltaManipulation().get_Scale().get_Y() > 0.0 && (Math.Abs(1.0 - e.get_DeltaManipulation().get_Scale().get_X()) > 0.02 || Math.Abs(1.0 - e.get_DeltaManipulation().get_Scale().get_Y()) > 0.02))
				{
					flag = true;
				}
				if (!flag && (Math.Abs(e.get_DeltaManipulation().get_Translation().get_X()) > 2.0 || Math.Abs(e.get_DeltaManipulation().get_Translation().get_Y()) > 2.0))
				{
					flag2 = (Math.Abs(e.get_CumulativeManipulation().get_Translation().get_X()) > 30.0 || Math.Abs(e.get_CumulativeManipulation().get_Translation().get_Y()) > 30.0);
				}
				if (flag || flag2)
				{
					this.isTap = false;
					if (this.lastTap != null)
					{
						this.lastTap.DoItNow();
						this.lastTap = null;
					}
				}
				if (this.isTap && PhysicsHelper.ExceedsThreshold(TimeSpan.FromTicks(now.get_Ticks() - this.tapStartTimestamp), 2000L))
				{
					this.FireTapAndHoldEvent(sender, new TapAndHoldGestureEventArgs
					{
						Origin = origin
					});
					this.isTap = false;
					e.Complete();
				}
				if (flag)
				{
					if (e.get_DeltaManipulation().get_Scale().get_X() >= 1.0 && e.get_DeltaManipulation().get_Scale().get_Y() >= 1.0)
					{
						this.FireStretchEvent(sender, new StretchGestureEventArgs
						{
							Origin = origin,
							Scale = e.get_DeltaManipulation().get_Scale()
						});
					}
					else
					{
						this.FirePinchEvent(sender, new PinchGestureEventArgs
						{
							Origin = origin,
							Scale = e.get_DeltaManipulation().get_Scale()
						});
					}
				}
				else
				{
					if (flag2)
					{
						this.FirePanEvent(sender, new PanGestureEventArgs
						{
							Origin = origin,
							Translation = e.get_DeltaManipulation().get_Translation()
						});
					}
				}
				this.lastTranslation = e.get_DeltaManipulation().get_Translation();
				return;
			}
		}
		private void OnManipulationCompleted(object sender, ManipulationCompletedEventArgs e)
		{
			DateTime now = DateTime.get_Now();
			if (e.get_Handled())
			{
				return;
			}
			e.set_Handled(true);
			UIElement uIElement = e.get_OriginalSource() as UIElement;
			UIElement uIElement2 = sender as UIElement;
			if (uIElement != null && uIElement2 != null)
			{
				Point origin = uIElement.TransformToVisual(uIElement2).Transform(e.get_ManipulationOrigin());
				if (this.isTap)
				{
					if (this.isTapPending && ManipulationHandler.IsDoubleTap(this.lastTapOrigin, this.lastTapTimestamp, origin, now.get_Ticks()))
					{
						if (this.lastTap != null)
						{
							this.lastTap.Cancel();
							this.lastTap = null;
						}
						this.isTapPending = false;
						this.FireDoubleTapEvent(sender, new DoubleTapGestureEventArgs
						{
							Origin = origin
						});
					}
					else
					{
						if (this.lastTap != null)
						{
							this.lastTap.DoItNow();
							this.lastTap = null;
						}
						this.isTapPending = true;
						this.lastTapTimestamp = now.get_Ticks();
						this.lastTapOrigin = origin;
						this.lastTap = new Timeout(delegate
						{
							this.FireTapEvent(sender, new TapGestureEventArgs
							{
								Origin = origin
							});
						}, 600L);
					}
				}
				else
				{
					this.isTapPending = false;
				}
				if (e.get_IsInertial() && (Math.Abs(this.lastTranslation.get_X()) > 3.0 || Math.Abs(this.lastTranslation.get_Y()) > 3.0) && e.get_TotalManipulation().get_Scale().get_X() == 0.0 && e.get_TotalManipulation().get_Scale().get_Y() == 0.0)
				{
					this.FireFlickEvent(sender, new FlickGestureEventArgs
					{
						Origin = origin,
						Velocity = e.get_FinalVelocities().get_LinearVelocity()
					});
				}
				return;
			}
		}
		private void FireTapEvent(object sender, GestureEventArgs e)
		{
			EventHandler<GestureEventArgs> tap = this.Tap;
			if (tap != null)
			{
				tap.Invoke(sender, e);
			}
		}
		private void FireDoubleTapEvent(object sender, GestureEventArgs e)
		{
			EventHandler<GestureEventArgs> doubleTap = this.DoubleTap;
			if (doubleTap != null)
			{
				doubleTap.Invoke(sender, e);
			}
		}
		private void FireTapAndHoldEvent(object sender, GestureEventArgs e)
		{
			EventHandler<GestureEventArgs> tapAndHold = this.TapAndHold;
			if (tapAndHold != null)
			{
				tapAndHold.Invoke(sender, e);
			}
		}
		private void FirePanEvent(object sender, GestureEventArgs e)
		{
			EventHandler<GestureEventArgs> pan = this.Pan;
			if (pan != null)
			{
				pan.Invoke(sender, e);
			}
		}
		private void FireFlickEvent(object sender, GestureEventArgs e)
		{
			EventHandler<GestureEventArgs> flick = this.Flick;
			if (flick != null)
			{
				flick.Invoke(sender, e);
			}
		}
		private void FirePinchEvent(object sender, GestureEventArgs e)
		{
			EventHandler<GestureEventArgs> pinch = this.Pinch;
			if (pinch != null)
			{
				pinch.Invoke(sender, e);
			}
		}
		private void FireStretchEvent(object sender, GestureEventArgs e)
		{
			EventHandler<GestureEventArgs> stretch = this.Stretch;
			if (stretch != null)
			{
				stretch.Invoke(sender, e);
			}
		}
	}
}
